package com.qys.livesMall.app.user.controller.app;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qys.livesMall.app.user.annotation.IpLimit;
import com.qys.livesMall.app.user.constants.RedisConstant;
import com.qys.livesMall.app.user.enums.SmsEnum;
import com.qys.livesMall.app.user.model.dto.app.*;
import com.qys.livesMall.app.user.model.entity.AppUserGoldAccount;
import com.qys.livesMall.app.user.model.entity.H2AppUser;
import com.qys.livesMall.app.user.model.entity.H2AppUserBalance;
import com.qys.livesMall.app.user.model.vo.TelephoneAreaCodeVO;
import com.qys.livesMall.app.user.model.vo.app.AppUserInfoVo;
import com.qys.livesMall.app.user.model.vo.app.AppUserInviteVO;
import com.qys.livesMall.app.user.model.vo.sys.AppUserNoticeVO;
import com.qys.livesMall.app.user.service.AppUserGoldAccountService;
import com.qys.livesMall.app.user.service.AppUserRelationService;
import com.qys.livesMall.app.user.service.IH2AppUserBalanceService;
import com.qys.livesMall.app.user.service.IH2AppUserService;
import com.qys.livesMall.app.user.utils.PasswordUtil;
import com.qys.livesMall.app.user.utils.SmsUtil;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.constants.SysConstants;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.common.utils.ip.IpUtil;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.view.BaseQuery;
import com.qys.livesMall.system.model.entity.H2SysConfig;
import com.qys.livesMall.system.service.IH2SysConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * app-用户
 * </p>
 *
 * @author dp
 * @since 2023-04-20
 */
@RestController
@RequestMapping("/app/user")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Tag(name = "app-用户信息")
public class H2AppUserController {

    private final IH2AppUserService appUserService;
    private final IH2AppUserBalanceService userBalanceService;
    private final AppUserGoldAccountService goldAccountService;
    private final IH2SysConfigService ih2SysConfigService;
    /**
     * 注册
     * @param userRegisterDTO
     * @param request
     * @return
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册")
    @IpLimit(key = "max_ip_registe",limitTips = "Limit the registration")
    public R<Void> register(@RequestBody @Validated AppUserRegisterDTO userRegisterDTO,HttpServletRequest request) {
        String ip = IpUtil.getIpAddr(request);
        appUserService.register(userRegisterDTO,ip);
        return R.ok();
    }

    @GetMapping("/info")
    @Operation(summary = "获取用户信息")
    public R<AppUserInfoVo> queryUserIno(@RequestParam(value = "userId", required = false) Long userId) {
        if (null== SecurityUtils.getUserId() && userId == null){
           return R.ok();
        }
        AppUserInfoVo appUserInfoVo = appUserService.queryUserIno(null == userId ? SecurityUtils.getUserId() : userId);

        //用户余额
        if (null == userId) {
            H2AppUserBalance userBalance = userBalanceService.queryByUserId(SecurityUtils.getUserId());
            if (null != userBalance) {
                appUserInfoVo.setBalance(userBalance.getBalance());
            }
            AppUserGoldAccount goldAccount=goldAccountService.getGoldAccountByUserId(SecurityUtils.getUserId());
            if (goldAccount!=null){
                appUserInfoVo.setGoldBalance(goldAccount.getGoldAmount());
            }
            //记录用户活跃
            appUserService.activeUser(SecurityUtils.getUserId());
        }

        return R.ok(appUserInfoVo);
    }

    @PostMapping("/change/password")
    @Operation(summary = "修改密码")
    public R<Void> changePassword(@RequestBody @Validated PasswordDTO passwordDTO) {

        if (passwordDTO.getType() == (byte) 0 || passwordDTO.getType() == (byte) 4) {
            Pattern pattern = Pattern.compile("^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).{8,}$");
            Matcher matcher = pattern.matcher(passwordDTO.getPassword());
            if (!matcher.matches()) {
                return R.fail(MessageUtils.message("old.new.password.rule"));
            }
        }

        if (passwordDTO.getType() != (byte) 4 && Objects.equals(passwordDTO.getPassword(), passwordDTO.getOldPassword())) {
            return R.fail(MessageUtils.message("old.new.password.equal"));
        }

        if (!Objects.equals(passwordDTO.getRePassword(), passwordDTO.getPassword())) {
            return R.fail(MessageUtils.message("old.new.password.not.equal"));
        }

        if (passwordDTO.getType() == 1 && passwordDTO.getPassword().length() != 6) {
            return R.fail(MessageUtils.message("pay.pwd.length"));
        }

        H2AppUser appUser = null;
        if (passwordDTO.getType() == (byte) 4) {
            appUser = appUserService.getbyUserName(passwordDTO.getUsername());
            H2SysConfig h2SysConfig=ih2SysConfigService.getConfigByKey("verifyBoolean");
            if (null != h2SysConfig && h2SysConfig.getValue().equals("true")) {
                if (appUser == null || !String.valueOf(appUser.getMobile()).equals(passwordDTO.getPhone())) {
                    throw new QysException(MessageUtils.message("user.phone.inconsistent"));
                }
            } else {
                if (appUser == null || !String.valueOf(appUser.getEmail()).equals(passwordDTO.getEmail())) {
                    throw new QysException(MessageUtils.message("user.mail.inconsistent"));
                }
            }
        }
        appUserService.changePassword(passwordDTO, passwordDTO.getType() != (byte) 4 ? SecurityUtils.getUserId() : Long.valueOf(appUser.getId()));

        return R.ok();
    }

    @PostMapping("/set/password")
    @Operation(summary = "设置密码")
    public R<Void> setPassword(@RequestBody @Validated PasswordDTO passwordDTO) {
        //密码不一致
        if (!Objects.equals(passwordDTO.getRePassword(), passwordDTO.getPassword())) {
            return R.fail(MessageUtils.message("old.new.password.not.equal"));
        }

        appUserService.setPassword(passwordDTO, SecurityUtils.getUserId());

        return R.ok();
    }

    @PostMapping("/logoff")
    @Operation(summary = "注销")
    public R<Void> logoff(HttpServletRequest request) {
        //退出登录
        String token = request.getHeader(SysConstants.AUTHORIZATION);
        appUserService.loginOut(token);

        //删除用户
        appUserService.removeById(SecurityUtils.getUserId());
        return R.ok();
    }

    @PostMapping("/check/bank/password")
    @Operation(summary = "用户提现密码校验")
    public R<Void> checkBankPassword(@RequestParam String password) {
        H2AppUser appUser = appUserService.getById(SecurityUtils.getUserId());
        if (null == appUser) {
            throw new QysException(MessageUtils.message("app.getuser.error"));
        }
        //未设置密码
        if (StringUtils.isBlank(appUser.getUserWithdrawalPassword())) {
            throw new QysException(MessageUtils.message("security.password.error"));
        }

        // 密码错误
        String newPwd = PasswordUtil.encrypt(password, appUser.getUserName(), appUser.getSalt());
        if (!Objects.equals(newPwd, appUser.getUserWithdrawalPassword())) {
            throw new QysException(MessageUtils.message("password.error"));
        }
        return R.ok();
    }

    @PutMapping("/edit")
    @Operation(summary = "修改用户信息")
    public R<Void> editUserInfo(@RequestBody AppUserEditDTO editDTO) {
        if (null == editDTO.getId()){
            editDTO.setId(String.valueOf(SecurityUtils.getUserId()));
        }
        appUserService.save(editDTO);
        return R.ok();
    }

    @PostMapping("/invite/history")
    @Operation(summary = "用户邀请记录查询")
    public R<Page<AppUserInviteVO>> queryUserInviteHistory(@RequestBody BaseQuery baseQuery) {
        baseQuery.setId(String.valueOf(SecurityUtils.getUserId()));
        return R.ok(appUserService.queryUserInviteHistory(baseQuery));
    }

    @GetMapping("/check/password")
    @Operation(
            summary = "用户是否设置密码信息",
            parameters = {
                    @Parameter(name = "type", description = "类型(0支付密码,1店铺密码,2主播密码)", required = true)
            }
    )
    public R<Integer> checkHavePassword(@RequestParam() Byte type) {
        H2AppUser appUser = appUserService.getById(SecurityUtils.getUserId());
        if (null == appUser) {
            throw new QysException(MessageUtils.message("app.getuser.error"));
        }

        int result = Constants.YesNoInt.NO;
        switch (type) {
            //支付密码
            case 0 -> {
                if (StringUtils.isNotBlank(appUser.getUserWithdrawalPassword())) {
                    result = Constants.YesNoInt.YES;
                }
            }
            //店铺提现
            case 1 -> {
                if (StringUtils.isNotBlank(appUser.getStoreWithdrawalPassword())) {
                    result = Constants.YesNoInt.YES;
                }
            }
            //主播提现
            case 2 -> {
                if (StringUtils.isNotBlank(appUser.getAnchorWithdrawalPassword())) {
                    result = Constants.YesNoInt.YES;
                }
            }
        }

        return R.ok(result);
    }

    @PostMapping("/sendMessage/{type}/{phoneNumber}")
    @Operation(summary = "发送验证短信（type：1注册验证，2忘记密码验证, 3主播申请）")
    public R<?> sendMessage(@PathVariable Integer type, @PathVariable String phoneNumber) {
        boolean ok = false;
        if(1 == type){
            ok = SmsUtil.sendMessage(phoneNumber, SmsEnum.REGISTER);
        } else if (2 == type) {
            ok = SmsUtil.sendMessage(phoneNumber, SmsEnum.FORGOT_PASSWORD);
        } else if (3 == type) {
            ok = SmsUtil.sendMessage(phoneNumber, SmsEnum.AHCNOR_APPLY);
        }

        if(!ok){
            return R.fail();
        }
        return R.ok();
    }

    @GetMapping("/getInternationalTelephoneAreaCode")
    @Operation(summary = "获取国际电话区号")
    public R<List<TelephoneAreaCodeVO>> getInternationalTelephoneAreaCode() {
        return R.ok(appUserService.getInternationalTelephoneAreaCode());
    }

    @PostMapping("/check/username/{username}")
    @Operation(summary = "获取校验用户是否存在")
    public R<?> checkUsername(@PathVariable String username) {
        H2AppUser appUser = appUserService.getbyUserName(username);
        if (null == appUser) {
            return R.ok(false);
        }
        return R.ok(true);
    }


    @PostMapping("/getUser/phone/{username}")
    @Operation(summary = "获取用户手机号和邮件")
    public R<AppUserNoticeVO> getUserphone(@PathVariable String username) {
        H2AppUser appUser = appUserService.getbyUserName(username);
        AppUserNoticeVO appUserNoticeVO=new AppUserNoticeVO();
        if (null == appUser) {
            appUserNoticeVO.setMobile("");
            appUserNoticeVO.setEmail("");
        }else {
            appUserNoticeVO.setMobile(appUser.getMobile());
            appUserNoticeVO.setEmail(appUser.getEmail());
        }
        return R.ok(appUserNoticeVO);
    }

    @GetMapping("/updateUserUID")
    @Operation(summary = "重新更新用户uid")
    public R<?> getUserphone() {
        List<H2AppUser> appUsers=appUserService.list();
        for (H2AppUser appUser :appUsers){
            appUser.setUserRandomId(appUserService.getRandomId());
        }
        appUserService.updateBatchById(appUsers);
       return R.ok();
    }


    @PostMapping("/userBindingPhone")
    @Operation(summary = "用户绑定手机号")
    public R<Void> userBindingPhone(@RequestBody @Validated AppUserRegisterPhoneDTO dto) {
        appUserService.userBindingPhone(dto);
        return R.ok();
    }

    @PostMapping("/userBindingMail")
    @Operation(summary = "用户绑定邮箱")
    public R<Void> userBindingMail(@RequestBody @Validated AppUserRegisterMailDTO dto) {
        appUserService.userBindingMail(dto);
        return R.ok();
    }

    @PostMapping("/sendMail/{mailNumber}")
    @Operation(summary = "发送用户邮箱验证")
    public R<?> sendMail(@PathVariable String mailNumber) {
        appUserService.sendMail(mailNumber, RedisConstant.MAILUSERREGISTER);
        return R.ok();
    }
}
